#include "kernel.h"

struct video_pos *pos;
unsigned char *video_mem;

/*
 *
 * intlen function helper
 *
 */
int intlen_helper(unsigned x) {
    if(x>=1000000000) return 10;
    if(x>=100000000) return 9;
    if(x>=10000000) return 8;
    if(x>=1000000) return 7;
    if(x>=100000) return 6;
    if(x>=10000) return 5;
    if(x>=1000) return 4;
    if(x>=100) return 3;
    if(x>=10) return 2;
    return 1;
}

/*
 *
 * hexlen function helper
 *
 */
int hexlen_helper(unsigned x) {
    if(x> 0xffffffff) return 9;
    if(x> 0xfffffff) return 8;
    if(x> 0xffffff) return 7;
    if(x> 0xfffff) return 6;
    if(x> 0xffff) return 5;
    if(x> 0xfff) return 4;
    if(x> 0xff) return 3;
    if(x> 0xf) return 2;
    return 1;
}

/*
 *
 * Calculate length of an integer in number of bytes
 *
 */
int intlen(unsigned int x) {
    return intlen_helper(x);
}

/*
 *
 * Calculate the length of hex number
 *
 */
int hexlen(unsigned int x) {
    return hexlen_helper(x);
}

/*
 *
 * Initialize the->line number variable
 *
 */
void init_video(void) {
	pos->line =  0;
	pos->dot = 0;
}

/*
 *
 * clears the screen
 *
 */
void cls()
{
	int iter;
	video_mem = VIDEOMEM_BEGIN;
	for (iter = 0; iter < MAX_LINES * MAX_DOTS_PER_LINE; iter +=2)
	{
		*(video_mem + iter) = BLANK;
		*(video_mem + iter + 1) = WHITE_COLOR;
	}		
	pos->line =  1;
	pos->dot = 0;
}

/*
 *
 * Prints something
 *
 */
void print(void *message)
{
	if (! message) {
		return;
	}
	unsigned char *input = message;
	while (*input != '\0')
	{
		printc((char) *input);
		input ++;
	};

}

/*
 *
 * Clears a line
 *
 */
void line_clear(int line_no)
{
	int iter;
	video_mem = VIDEOMEM_BEGIN;
	
	for(iter =line_no * MAX_DOTS_PER_LINE; iter < (line_no + 1) * MAX_DOTS_PER_LINE; iter ++)
	{
	      *(video_mem + iter) = BLANK;
	      iter += 1;
	      *(video_mem + iter) = WHITE_COLOR;
	}
}

/*
 *
 * scroll
 *
 */
void scroll()
{
	video_mem = VIDEOMEM_BEGIN;
	
	line_clear(0);
	memcpy(video_mem, (video_mem + MAX_DOTS_PER_LINE), (MAX_DOTS_PER_LINE + 1) * MAX_LINES);
	pos->line =  MAX_LINES - 1;
}

/*
 *
 * Print a character
 *
 */
void printc(unsigned char message)
{
	video_mem = VIDEOMEM_BEGIN;

	if (pos->line == MAX_LINES ) {
		scroll();
	}

	if (message == '\n') {
		pos->line += 1;
		pos->dot = 0;
		return;
	}

	video_mem += pos->line * MAX_DOTS_PER_LINE + pos->dot;
	*video_mem = message;
	video_mem ++;
	*video_mem = WHITE_COLOR;

	pos->dot += 2;

}

/*
 *
 * Hex to Char
 *
 */
unsigned char htoc(unsigned int h) {
	return htoa_map[h];
}

/*
 *
 * Convert Char to Hex
 *
 */
unsigned int ctoh(unsigned char c) {
	return atoh_map[(int) c];
}

/*
 *
 * Hex to string
 *
 */
void htos (unsigned int num, unsigned char *hex_string)
{
        int len = hexlen((unsigned int) num);

        int i = len - 1;
	while(i >= 0) {	
                hex_string[i] = htoc(num & 0xF);
                num = num >> 4;
		i --;
        }

        hex_string[len] = '\0';
}

/*
 *
 * String to hex number with direction
 *
 */

unsigned int stoh(unsigned char *str, int direction)
{
	unsigned int num = 0;
	int i = strlen(str) - 1;

	int j = 0;
	while(i >= 0) {
		if (direction == RIGHT_TO_LEFT) {
			num = num | (xor_helper[str[i] ^ 0xa] & 0xf) << (4 * i);
		} else {
			num = num | (xor_helper[str[j] ^ 0xa] & 0xf) << (4 * i);
		}
		i --;
		j ++;
	}
			 
	return num;
}

